﻿using System;
using System.Configuration;

namespace smp.RabbitMq.Configuration
{
    public class Connection : ConfigurationElement
    {
        [ConfigurationProperty("host", IsKey=true, IsRequired = true)]
        public string Host
        {
            get { return (string) this["host"]; }
        }

        [ConfigurationProperty("virtualhost", IsKey = true, IsRequired = false)]
        public string VirtualHost
        {
            get { return (string)this["virtualhost"]; }
        }

        [ConfigurationProperty("username", IsKey = true, IsRequired = true)]
        public string UserName
        {
            get { return (string) this["username"]; }
        }

        [ConfigurationProperty("password", IsKey = true, IsRequired = true)]
        public string Password
        {
            get { return (string)this["password"]; }
        }

        [ConfigurationProperty("port", IsKey = true, IsRequired = false)]
        public int? Port
        {
            get
            {
                var value = this["port"];
                if (value == null)
                    return null;
                int port;
                if (int.TryParse(value.ToString(), out port))
                    return port;
                return null;
            }
        }

        [ConfigurationProperty("exchange", IsKey = true, IsRequired = false)]
        public string Exchange
        {
            get { return (string)this["exchange"]; }
        }

        [ConfigurationProperty("routingkey", IsKey = true, IsRequired = false)]
        public string RoutingKey
        {
            get { return (string)this["routingkey"]; }
        }

        [ConfigurationProperty("exchangetype", IsKey = true, IsRequired = false)]
        public string ExchangeType
        {
            get { return (string)this["exchangetype"]; }
        }

        [ConfigurationProperty("durableexchange", IsKey = true, IsRequired = false)]
        public bool? DurableExchange
        {
            get { return (bool?) this["durableexchange"]; }
        }

        [ConfigurationProperty("autodeleteexchange", IsKey = true, IsRequired = false)]
        public bool? AutoDeleteExchange
        {
            get { return (bool?) this["autodeleteexchange"]; }
        }

        internal virtual IRabbitMqConfiguration GetConfiguration()
        {
            var config = new RabbitMqConfiguration
                       {
                           Host = Host,
                           VirtualHost = VirtualHost,
                           Username = UserName,
                           Password = Password,
                           Port = Port,
                           Exchange = Exchange,
                           ExchangeType = RabbitMqExchangeType,
                           RoutingKey = RoutingKey,
                           DurableExchange = !DurableExchange.HasValue || DurableExchange.Value,
                           AutoDeleteExchange = AutoDeleteExchange.HasValue && AutoDeleteExchange.Value
                       };
            return config;
        }

        private RabbitMqExchangeType RabbitMqExchangeType
        {
            get
            {
                RabbitMqExchangeType result;
                if(Enum.TryParse(ExchangeType, true, out result))
                    return result;
                return RabbitMqExchangeType.direct;
            }
        }
    }
    
    public class PublishConnection : Connection
    {
        [ConfigurationProperty("key", IsKey = true, IsRequired = true)]
        public string Key
        {
            get { return (string)this["key"]; }
        }
    }

    public class RequestConnection : Connection
    {
        [ConfigurationProperty("key", IsKey = true, IsRequired = true)]
        public string Key
        {
            get { return (string)this["key"]; }
        }

        [ConfigurationProperty("queue", IsKey = true, IsRequired = true)]
        public string Queue
        {
            get { return (string)this["queue"]; }
        }
        
        [ConfigurationProperty("durablequeue", IsKey = true, IsRequired = false)]
        public bool? DurableQueue
        {
            get { return (bool?)this["durablequeue"]; }
        }

        [ConfigurationProperty("autodeletequeue", IsKey = true, IsRequired = false)]
        public bool? AutoDeleteQueue
        {
            get { return (bool?)this["autodeletequeue"]; }
        }

        internal override IRabbitMqConfiguration GetConfiguration()
        {
            var config = (RabbitMqConfiguration)base.GetConfiguration();
            config.Queue = Queue;
            config.DurableQueue = !DurableExchange.HasValue || DurableExchange.Value;
            config.AutoDeleteQueue = AutoDeleteExchange.HasValue && AutoDeleteExchange.Value;
            return config;
        }
    }
    
    public class SubscribeConnection : Connection
    {
        [ConfigurationProperty("queue", IsKey = true, IsRequired = true)]
        public string Queue
        {
            get { return (string)this["queue"]; }
        }

        [ConfigurationProperty("errorqueue", IsKey = true, IsRequired = false)]
        public bool? ErrorQueue
        {
            get { return (bool?) this["errorqueue"]; }
        }

        [ConfigurationProperty("durablequeue", IsKey = true, IsRequired = false)]
        public bool? DurableQueue
        {
            get { return (bool?) this["durablequeue"]; }
        }

        [ConfigurationProperty("autodeletequeue", IsKey = true, IsRequired = false)]
        public bool? AutoDeleteQueue
        {
            get { return (bool?) this["autodeletequeue"]; }
        }

        internal override IRabbitMqConfiguration GetConfiguration()
        {
            var config = (RabbitMqConfiguration)base.GetConfiguration();
            config.Queue = Queue;
            config.DurableQueue = !DurableExchange.HasValue || DurableExchange.Value;
            config.AutoDeleteQueue = AutoDeleteExchange.HasValue && AutoDeleteExchange.Value;
            config.ErrorQueue = ErrorQueue.HasValue && ErrorQueue.Value;
            return config;
        }
    }
}
